package com.cccyy.xml.xstream;

import com.cccyy.xml.vo.*;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

public class TestXStreamBackToMap {

    public static void main(String[] args) {
        HashMap<Object, Object> sendMap = new HashMap<>();
        sendMap.put("CLIENT_TYPE", "100");
        sendMap.put("CLIENT_NAME", "Austin");
        sendMap.put("CH_CLIENT_NAME", "张三");
        sendMap.put("SEX", "M");
        sendMap.put("COUNTRY", "ZHN");
        sendMap.put("BIRTH_DATE", "19980723");
        sendMap.put("DOCUMENT_TYPE", "001");
        sendMap.put("GLOBAL_ID", "310010199807236453");
        long time1 = System.currentTimeMillis();
        //测试java对象转xml，java对象中包含集合对象
        Date date = new Date();
        //格式化  交易日期  YYYYMMDD  yyyyMMddHHmmssSSS
        String tranDate = getFormatTime(date, "yyyyMMdd");
        //格式化  交易时间  HHMMSSNNN
        String timeStamp = getFormatTime(date, "HHmmssSSS");

        //组装报文
        Service service = new Service();
        SysHeader sysHeader = new SysHeader();
        Data sysData = new Data();
        sysData.setName("SYS_HEAD");
        Struct sysStruct = new Struct();
        ArrayList<Data> sysDataList = new ArrayList<>();
        fillSysHeaderString(sysDataList, "SERVICE_CODE", "SVR_INQUIRY");
        fillSysHeaderString(sysDataList, "TRAN_CODE", "");
        fillSysHeaderString(sysDataList, "TRAN_TYPE", "");
        fillSysHeaderString(sysDataList, "REVERSAL_TRAN_TYPE", "");
        fillSysHeaderString(sysDataList, "TRAN_MODE", "ONLINE");
        fillSysHeaderString(sysDataList, "SOURCE_TYPE", "MM");
        fillSysHeaderString(sysDataList, "BRANCH_ID", "0101");
        fillSysHeaderString(sysDataList, "USER_ID", "00020999");
        fillSysHeaderString(sysDataList, "TRAN_DATE", tranDate);
        fillSysHeaderString(sysDataList, "TRAN_TIMESTAMP", timeStamp);
        fillSysHeaderString(sysDataList, "SERVER_ID", "127.0.0.1");
        fillSysHeaderString(sysDataList, "WS_ID", "9999");
        fillSysHeaderString(sysDataList, "USER_LANG", "CHINESE");
        fillSysHeaderString(sysDataList, "SEQ_NO", String.valueOf(System.currentTimeMillis()));
        fillSysHeaderString(sysDataList, "PROGRAM_ID", "MM");
        fillSysHeaderString(sysDataList, "AUTH_USER_ID", "");
        fillSysHeaderString(sysDataList, "AUTH_PASSWORD", "");
        fillSysHeaderString(sysDataList, "AUTH_FLAG", "M");
        fillSysHeaderString(sysDataList, "APPR_USER_ID", "");
        fillSysHeaderString(sysDataList, "APPR_FLAG", "A");
        fillSysHeaderString(sysDataList, "SOURCE_BRANCH_NO", "");
        fillSysHeaderString(sysDataList, "DEST_BRANCH_NO", "");
        fillSysHeaderString(sysDataList, "MODULE_ID", "CL");
        fillSysHeaderString(sysDataList, "MESSAGE_TYPE", "1400");
        fillSysHeaderString(sysDataList, "MESSAGE_CODE", "9105");
        fillSysHeaderString(sysDataList, "FILE_PATH", "");
        sysStruct.setStruct(sysDataList);
        sysData.setStruct(sysStruct);
        sysHeader.setData(sysData);
        service.setSysheader(sysHeader);

        AppHeader appHeader = new AppHeader();
        Data appData = new Data();
        appData.setName("APP_HEAD");
        Struct appStruct = new Struct();
        ArrayList<Data> appDataList = new ArrayList<>();
        fillSysHeaderString(appDataList, "PGUP_OR_PGDN", "");
        fillSysHeaderString(appDataList, "TOTAL_NUM", "");
        fillSysHeaderString(appDataList, "CURRENT_NUM", "");
        fillSysHeaderString(appDataList, "PAGE_START", "");
        fillSysHeaderString(appDataList, "PAGE_END", "");
        appStruct.setStruct(appDataList);
        appData.setStruct(appStruct);
        appHeader.setData(appData);
        service.setAppheader(appHeader);

        LocalHeader localHeader = new LocalHeader();
        Data localData = new Data();
        localData.setName("LOCAL_HEAD");
        Struct localStruct = new Struct();
        localData.setStruct(localStruct);
        localHeader.setData(localData);
        service.setLocalheader(localHeader);

        Body body = new Body();
        ArrayList<Data> dataList = new ArrayList<>();
        buildBodySend(dataList, sendMap);
        body.setData(dataList);
        service.setBody(body);

        String xml = XStreamUtil.beanToXml(service);
        String sle = String.valueOf(xml.length());
        StringBuffer le = new StringBuffer();
        if (8 > sle.length()) {
            for (int i = 0; i < 8 - sle.length(); i++) {
                le.append("0");
            }
            le.append(sle);
        }

        xml = le.append(xml).toString();
        System.out.println(xml);

        //测试xml转java对象
        xml = "00016596<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<service>\n" +
                "<sys-header>\n" +
                "<data name=\"SYS_HEAD\">\n" +
                "<struct>\n" +
                "<data name=\"SEQ_NO\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"14\">20180709180852</field>\n" +
                "</data>\n" +
                "<data name=\"TRAN_DATE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"8\">20180720</field>\n" +
                "</data>\n" +
                "<data name=\"RET\">\n" +
                "<array>\n" +
                "<struct>\n" +
                "<data name=\"RET_CODE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"6\">000000</field>\n" +
                "</data>\n" +
                "<data name=\"RET_MSG\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"7\">Success</field>\n" +
                "</data>\n" +
                "</struct>\n" +
                "</array>\n" +
                "</data>\n" +
                "</struct>\n" +
                "</data>\n" +
                "</sys-header>\n" +
                "<app-header>\n" +
                "<data name=\"APP_HEAD\">\n" +
                "<struct/>\n" +
                "</data>\n" +
                "</app-header>\n" +
                "<local-header>\n" +
                "<data name=\"LOCAL_HEAD\">\n" +
                "<struct/>\n" +
                "</data>\n" +
                "</local-header>\n" +
                "<body>\n" +
                "<data name=\"OP_CLIENT\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"1\">Y</field>\n" +
                "</data>\n" +
                "<data name=\"UPDATE_USER\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"8\">00020137</field>\n" +
                "</data>\n" +
                "<data name=\"CONTACT_INFO\">\n" +
                "<array>\n" +
                "<struct>\n" +
                "<data name=\"PREF_FLAG\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"1\">Y</field>\n" +
                "</data>\n" +
                "<data name=\"POSTAL_CODE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"6\">111111</field>\n" +
                "</data>\n" +
                "</struct>\n" +
                "<struct>\n" +
                "<data name=\"PREF_FLAG\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"1\">N</field>\n" +
                "</data>\n" +
                "<data name=\"POSTAL_CODE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"6\">111111</field>\n" +
                "</data>\n" +
                "</struct>\n" +
                "</array>\n" +
                "</data>\n" +
                "<data name=\"CLIENT_CITY\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"4\">xxxx</field>\n" +
                "</data>\n" +
                "<data name=\"DOCUMENT_INFO\">\n" +
                "<array>\n" +
                "<struct>\n" +
                "<data name=\"PREF_FLAG\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"1\">N</field>\n" +
                "</data>\n" +
                "<data name=\"ISS_DATE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"8\">20170520</field>\n" +
                "</data>\n" +
                "</struct>\n" +
                "<struct>\n" +
                "<data name=\"PREF_FLAG\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"1\">Y</field>\n" +
                "</data>\n" +
                "<data name=\"ISS_DATE\">\n" +
                "<field type=\"string\" scale=\"0\" length=\"8\">20180118</field>\n" +
                "</data>\n" +
                "</struct>\n" +
                "</array>\n" +
                "</data>\n" +
                "</body>\n" +
                "</service>";
        String substring = xml.substring(8);
        Service resultService = (Service) XStreamUtil.xmlToBean(substring);
        //返回报文-头部解析header-RET
        Map<Object, Object> responseMap = new HashMap<>();
        List<Data> sysArrayRetDataList = resultService.getSysheader().getData().getStruct().getStruct();
        for (Data sysArrayRetData : sysArrayRetDataList) {
            if ("RET".equals(sysArrayRetData.getName())) {
                List<Struct> sysArrayRetStructList = sysArrayRetData.getArray().getStruct();
                for (Struct sysArrayRetStruct : sysArrayRetStructList) {
                    List<Data> sysRetDataList = sysArrayRetStruct.getStruct();
                    for (Data sysRetData : sysRetDataList) {
                        responseMap.put(sysRetData.getName(), sysRetData.getField().getText());
                    }
                }
            }
        }
        //返回报文-体部解析-body
        List<Data> bodyDataListArray = resultService.getBody().getData();
        for (Data bodyArrayRetData : bodyDataListArray) {
            //对应返回报文中array标签，内部的数据用map存放，key值重复
            ArrayList<Map> mapArrayList = new ArrayList<>();
            if (StringUtils.isEmpty(bodyArrayRetData.getField())) {
                List<Struct> bodyArrayRetStructList = bodyArrayRetData.getArray().getStruct();
                for (Struct bodyArrayRetStruct : bodyArrayRetStructList) {
                    List<Data> bodyRetDataList = bodyArrayRetStruct.getStruct();
                    HashMap<String, String> structMap = new HashMap<>();
                    for (Data sysRetData : bodyRetDataList) {
                        if (!StringUtils.isEmpty(sysRetData.getField().getText())) {
                            structMap.put(sysRetData.getName(), sysRetData.getField().getText());
                        }
                    }
                    mapArrayList.add(structMap);
                }
                responseMap.put(bodyArrayRetData.getName(), mapArrayList);
            } else {
                responseMap.put(bodyArrayRetData.getName(), bodyArrayRetData.getField().getText());
            }
        }
        responseMap.put("lastTime", date);
        long time2 = System.currentTimeMillis();
        System.out.println((time2 - time1) + "ms");
    }

    private static void buildArrayBack(String arrayName, Data arrayData, ArrayList<Data> dataArrayList, Map<Object, Object> map) {
        Struct structOut = new Struct();
        Data data = new Data();
        data.setName(arrayName);
        Array array = new Array();
        ArrayList<Data> arrayDataList = new ArrayList<>();
        ArrayList<Struct> structDataList = new ArrayList<>();
        Struct struct = new Struct();
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            fillSysHeaderString(arrayDataList, entry.getKey().toString(), entry.getValue().toString());
        }
        struct.setStruct(arrayDataList);
        structDataList.add(struct);
        array.setStruct(structDataList);
        data.setArray(array);
        dataArrayList.add(data);
        structOut.setStruct(dataArrayList);
        arrayData.setStruct(structOut);
    }

    private static void buildBodySend(ArrayList<Data> dataList, Map<Object, Object> map) {
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            fillSysHeaderString(dataList, entry.getKey().toString(), entry.getValue().toString());
        }
    }

    private static String getFormatTime(Date date, String yyyymmdd) {
        SimpleDateFormat sf = new SimpleDateFormat(yyyymmdd);
        return sf.format(date).replaceAll(":", "");
    }

    private static void fillSysHeaderString(ArrayList<Data> dataList, String headerName, String text) {
        Data data = new Data();
        data.setName(headerName);
        Field field = new Field();
        field.setLength(String.valueOf(text.length()));
        field.setType("string");
        field.setText(text);
        data.setField(field);
        dataList.add(data);
    }
}
